﻿using System.Collections.Generic;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.UI;
using Microsoft.EntityFrameworkCore;
using MPACore.Phonebook.PhoneBooks.Dto;
using MPACore.Phonebook.PhoneBooks.Person.Dto;

namespace MPACore.Phonebook.PhoneBooks.Persons
{
    public class PersonAppService : PhonebookAppServiceBase, IPersonAppService
    {
        private readonly IRepository<Phonebooks.Persons.Person> _personRepository;
        public PersonAppService(IRepository<Phonebooks.Persons.Person> personRepository)
        {
            _personRepository = personRepository;
        }

        /// <summary>
        /// 创建或者更新联系人信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task CreateOrUpdatePersonAsync(CreateOrUpdatePersonInput input)
        {
            if (input.PersonEditDto.Id.HasValue)
            {
                await UpdatePersonAsync(input.PersonEditDto);
            }
            else
            {
                await CreatePersonAsync(input.PersonEditDto);
            }
        }

        /// <summary>
        /// 删除联系人
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task DeletePersonAsync(EntityDto input)
        {
            var entity = _personRepository.GetAsync(input.Id);
            if (entity == null) throw new UserFriendlyException("要删除的用户不存在");
            await _personRepository.DeleteAsync(input.Id);
        }

        /// <summary>
        /// 获取分页的联系人信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<PersonListDto>> GetPagedPersonAsync(GetPersonInput input)
        {
            var query = _personRepository.GetAllIncluding(a => a.PhoneNumbers);
            var totalCount = await query.CountAsync();
            var result = await query.OrderBy(input.Sorting).PageBy(input).ToListAsync();
            var dtos = result.MapTo<List<PersonListDto>>();
            return new PagedResultDto<PersonListDto>(totalCount, dtos);
        }

        /// <summary>
        /// 根据Id获取联系人信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PersonListDto> GetPersonByIdAsync(NullableIdDto input)
        {
            var entity = await _personRepository.GetAllIncluding(a => a.PhoneNumbers).FirstOrDefaultAsync(a => a.Id == input.Id.Value);
            return entity.MapTo<PersonListDto>();
        }

        /// <summary>
        /// 更新联系人信息
        /// </summary>
        /// <returns></returns>
        protected async Task UpdatePersonAsync(PersonEditDto input)
        {
            var entity = await _personRepository.GetAsync(input.Id.Value);
            await _personRepository.UpdateAsync(input.MapTo(entity));
        }

        /// <summary>
        /// 创建新联系人
        /// </summary>
        /// <returns></returns>
        protected async Task CreatePersonAsync(PersonEditDto input)
        {
            var entity = input.MapTo<Phonebooks.Persons.Person>();
            await _personRepository.InsertAsync(entity);
        }

        /// <summary>
        /// 获取用于编辑的联系人信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<GetPersonForEditOutput> GetPersonForEditAsync(NullableIdDto input)
        {
            var output = new GetPersonForEditOutput();
            PersonEditDto personEditDto;
            if (input.Id.HasValue)
            {
                var entity = await _personRepository.GetAllIncluding(a => a.PhoneNumbers).FirstOrDefaultAsync(a => a.Id == input.Id.Value);
                personEditDto = entity.MapTo<PersonEditDto>();
            }
            else
            {
                personEditDto = new PersonEditDto();
            }
            output.Person = personEditDto;
            return output;
        }
    }
}
